
            <!DOCTYPE html>
            <html lang="en">
            <head>
                <meta charset="UTF-8">
                <title>Kubernetes弃用Dockershim，转向Containerd：影响及如何应对</title>
            </head>
            <body>
            <a href="https://andyoung.blog.csdn.net">原作者博客</a>
            <div id="content_views" class="markdown_views prism-atom-one-light">
                    <svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
                        <path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
                    </svg>
                    <p>Kubernetes1.24 版本发布时，正式宣布弃用 Dockershim，转向 Containerd 作为默认的容器运行环境。Kubernetes 以 CRI(Container Runtime Interface) 容器运行时接口制定接入准则，用户可以使用 Containerd、CRI-O、CRI- Dockerd 及其他容器运行时作为 Kubernetes 的容器引擎。</p> 
<h3><a id="Kubernetes__Dockershim_2"></a><strong>Kubernetes 为何弃用 Dockershim？</strong></h3> 
<p>Docker 在早期没有实现 Container Runtime Interface (CRI)，而 CRI 是 Kubernetes 后来增加的对额外运行时的支持标准。Dockershim 的存在是为了支持将 Docker 硬编码到 Kubernetes 中，但随着容器化成为行业标准，Kubernetes 项目增加了对额外运行时的支持，比如通过 Container Runtime Interface (CRI) 容器运行时接口来支持运行容器。因此，在 Kubernetes1.20 版本发布的时候提到未来会弃用 Dockershim 引擎，而在 Kubernetes1.24 版本发布时， 正式弃用之。</p> 
<h3><a id="_Containerd__6"></a><strong>什么是 Containerd ？</strong></h3> 
<p>containerd 是一种容器运行时引擎，原属于 Docker 的组件的一部分，主要提供容器生命周期管理（从创建到销毁容器）、拉取和推送镜像、存储管理（管理镜像及容器数据的存储）、调用 runc 容器运行等，现已由开源社区拆分脱离出来单独作为容器运行时项目。</p> 
<p>在 Kubernetes 中，Containerd 作为容器运行环境，负责管理 Pod 的生命周期，包括容器的创建、启动、停止和删除等操作。与 Dockershim 相比，Containerd 具有更好的性能、更强的可扩展性以及更简洁的架构。</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/ad111af9695e92032e3f8b885d4cf9be.png" alt=""></p> 
<h3><a id="_16"></a><strong>容器运行底层组件有哪些关系？</strong></h3> 
<p>Docker Client 和 Docker Daemon：Docker Client 是 Docker 的客户端，它可以通过命令行或 API 向 Docker Daemon 发送请求。Docker Daemon 是 Docker 的核心组件，负责管理镜像、容器、网络和卷等资源，并将 Docker API 暴露给客户端。</p> 
<p>Docker 镜像和 Docker 容器：Docker 镜像是只读的模板，包含了所有用于运行应用程序所需要的代码、库文件、环境变量和配置文件等内容。Docker 容器是基于 Docker 镜像创建的可运行实例。每个容器都是一个独立的、轻量级的操作系统，它们之间相互隔离并且可以共享主机的内核。</p> 
<p>CRI（Container Runtime Interface）和容器运行时：CRI 是 Kubernetes 的容器运行时标准接口，满足这个标准的所有容器运行时都可以被使用。容器运行时则提供了一个轻量级的容器运行环境，用于创建、启动和停止容器。</p> 
<p>OCI（Open Container Initiative）和 runc：OCI 是一个开放的容器组织，它制定了容器运行时的规范，包括运行时规范、容器镜像规范等。runc 是 OCI 标准的一个参考实现，它与容器所依赖的 cgroup/linux kernel 等进行交互，是容器最终运行的形态之一。</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/e1a32aa88f1133f30d79698e2d37d785.png" alt=""></p> 
<h3><a id="Containerd__Kubernetes__30"></a><strong>Containerd 在 Kubernetes 的运行变化</strong></h3> 
<p>在 Kubernetes 1.24 版本以前，Kubernetes 通过调用 Docker 命令来创建容器。具体来说，Kubernetes 将任务发送给 Docker 客户端，然后 Docker 客户端通过与 Docker 守护进程（daemon）通信来创建容器。Docker 守护进程会通过 Image 模块下载镜像并保存，然后通过 client 调用 containerd 创建并运行容器。在这个过程中，如果需要给容器添加持久化存储，可以使用 volume 参数；如果需要配置容器网络，可以通过 network 参数来实现。</p> 
<p>然而，Kubernetes 提供了更强大的卷挂载能力和集群级别的网络能力。在集群中，kubelet 只会使用到 Docker 提供的镜像下载和容器管理功能，而编排、网络、存储等功能都不会用到。</p> 
<p>在 Kubernetes 1.24 版本以后，Containerd 作为容器运行时被引入，带来了创建 Pod 所需的所有功能。与之前的方案相比，这不仅带来了更纯粹的功能模块，而且缩短了调用链，提高了系统的效率和稳定性。因此，用户可以使用 Containerd、CRI-O、CRI-Dockerd 及其他容器运行时作为 Kubernetes 的容器引擎。</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/2f836744e837ff802ad598496b721b67.png" alt=""></p> 
<h3><a id="Containerd__Kubernetes__42"></a><strong>Containerd 在 Kubernetes 中的工作流</strong></h3> 
<ol><li> <p>Kubelet 通过 CRI 运行时服务 API 调用 CRI 插件来创建 Pod。</p> </li><li> <p>CRI 创建一个特殊的沙箱容器（pause 容器），并将其放置在 Pod 的 Cgroups 和 NameSpace 命名空间中。</p> </li><li> <p>CRI 使用 CNI 配置 Pod 的网络命名空间。</p> </li><li> <p>Kubelet 随后通过 CRI 镜像服务 API 调用 CRI 插件来拉取应用容器镜像。如果镜像不存在于节点上，CRI 会进一步使用 Containerd 来拉取镜像。</p> </li><li> <p>Kubelet 通过 CRI 运行时服务 API 调用 CRI，并使用拉取的容器镜像在 Pod 内创建和启动应用程序容器。</p> </li><li> <p>CRI 创建应用程序容器，将其放入 Pod 的 Cgroups 和 NameSpace 中，然后启动 Pod 的新应用容器。</p> </li></ol> 
<p>在这些步骤之后，一个 Pod 及其相应的应用程序容器被创建并运行。</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/ae6bdf3eef09879e61b47b55f7666dff.jpeg" alt=""></p> 
<h3><a id="Kubernetes__Dockershim__62"></a><strong>Kubernetes 弃用 Dockershim 的影响</strong></h3> 
<p>容器镜像，由于 Docker 镜像符合 OCI 规范，因此可以直接使用而不受影响。此外，原镜像打包方式仍然可用，即使用 docker build 方式打包镜像。这意味着用户在构建和打包镜像时不需要做出任何改变</p> 
<p>Kubernetes 中的运行过程，作为终端用户（Kubernetes 使用者）基本也不会有任何影响，因为 Kubernetes 的使用逻辑没有任何变化。然而，与 Dockershim 相关的 API 接口已经弃用，如果创建了此类 CRD，需要注意修改相关代码。</p> 
<p>运维方式，节点后端运维时使用的命令由 docker 命令改为 containerd。如果旧环境使用的是 Dockershim 引擎，需要先改为 containerd 运行时再进行升级。运维人员则需要适应新的命令行工具和运行时环境。</p> 
<p>Kubernetes 弃用 Dockershim 而采用 containerd 作为容器运行时对用户和运维方式会有一些影响，但对于已经符合 OCI 规范的镜像和使用 docker build 方式打包镜像的用户来说，基本无感知。</p> 
<h3><a id="Kubernetes__72"></a><strong>Kubernetes 用户如何应对？</strong></h3> 
<p>用户需要按照 Kubernetes 官方提供的迁移指南进行操作。这包括更新 Kubernetes 版本、修改 Pod 配置文件、调整部署流程、更换镜像管理工具以及重新配置监控和日志采集工具等步骤。在迁移过程中，用户还需要注意测试新环境的稳定性和性能，确保迁移成功。</p> 
<p>在迁移过程中，用户可能会遇到各种问题，如配置错误、兼容性问题、性能下降等。为了解决这些问题，用户可以参考 Kubernetes 官方文档和社区资源，或者向灵雀云的服务团队寻求帮助和支持。此外，用户还可以在测试环境中模拟迁移过程，提前发现和解决问题。</p> 
<p>迁移到 Containerd 后，用户可以对系统进行一系列优化和改进，以提高性能和稳定性。例如，优化 Pod 的配置和部署流程、使用更高效的网络配置方式、改进监控和日志采集策略等。此外，用户还可以关注 Kubernetes 和 Containerd 的最新版本和功能更新，及时跟进技术发展趋势。</p> 
<p><img src="https://i-blog.csdnimg.cn/blog_migrate/e7ac949fb3d4482fa78f7923e77c45e1.png" alt=""></p> 
<h3><a id="_84"></a><strong>结论与展望</strong></h3> 
<p>Kubernetes 弃用 Dockershim 并转向 Containerd 已经成为一个明显的趋势信号。对于现有的 Kubernetes 用户来说，应尽快了解这一变化的影响和应对策略，找到适合自己的方案并尽早进行改进。未来，Kubernetes 与 Containerd 的发展趋势将更加紧密地结合在一起，共同推动容器技术的不断创新和发展。</p> 
<p>参考文档：</p> 
<ul><li> <p>https://kubernetes.io/zh-cn/blog/2022/02/17/dockershim-faq/</p> </li><li> <p>https://kubernetes.io/zh-cn/blog/2020/12/02/dont-panic-kubernetes-and-docker/</p> </li></ul>
                </div>
            </body>
            </html>
            